package Wrapper;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.LinkedList;

/**
 *
 * @author Said Mirza Pahlevi
 */
public class Wrapper {

    private StringBuffer xmlText = new StringBuffer("<?xml version=\"1.0\"?>");
    private String baseUrl;
    private int step;
    private int startPage;
    private LinkedList<Ruas> ruasList = new LinkedList<Ruas>();
    private String xmlFileName;
    private int limitPageNumber;
    private String rootName;
    private String itemStartMark;
    private String itemName;

    protected void setItemName(String itemName) {
        this.itemName = itemName;
    }

    protected void setItemStartMark(String itemStartMark) {
        this.itemStartMark = itemStartMark;
    }

    protected void setRootName(String rootName) {
        this.rootName = rootName;
    }

    protected void setBaseUrl(String baseUrl) {
        this.baseUrl = baseUrl;
    }

    protected void addRuas(Ruas ruas) {
        this.ruasList.add(ruas);
    }

    protected void setStartPage(int startPage) {
        this.startPage = startPage;
    }

    protected void setStep(int step) {
        this.step = step;
    }

    public void setXmlFileName(String xmlFileName) {
        this.xmlFileName = xmlFileName;
    }

    public void setLimitPageNumber(int limitPageNumber) {
        this.limitPageNumber = limitPageNumber;
    }

    private void retrievePages() {
        xmlText.append("\n" + "<" + rootName + ">");
        int max = startPage + (limitPageNumber - 1) * step;
        for (int i = startPage; i <= max; i += step) {
            // untuk mengganti startpage pada base URL
            String pageUrl = baseUrl.replaceAll("#", Integer.toString(i));
            System.out.println(pageUrl);
            extractData(getHtmlText(pageUrl));
        }
        xmlText.append("\n" + "</" + rootName + ">");
    }

    private String getHtmlText(String targetUrl) {
        String htmlText = null;
        try {
            URL pageUrl = new URL(targetUrl);
            URLConnection conn = pageUrl.openConnection();
            conn.setAllowUserInteraction(false);
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(pageUrl.openStream()));
            StringBuilder sb = new StringBuilder();
            String inputLine;
            while ((inputLine = bufferedReader.readLine()) != null) {
                sb.append(inputLine);
            }
            bufferedReader.close();
            htmlText = sb.toString();
        } catch (IOException ex) {
        }
        
        return htmlText;
    }

    /**
     * Extract components of item: author, title and description
     * @param anAuthorPubList HTML anAuthorPubList of a specific author's bibliography
     */
    private void extractData(String htmlPage) {
        // pecah-pecah item berdasarkan startmark
        String[] itemList = htmlPage.split(itemStartMark);

        // untuk setiap item, extract komponen penyusunnya (fields)
        for (String item : itemList) {
            System.out.println(item);
            String result = getItemFields(item);
            if (!result.equals("failed")) {
                xmlText.append("\n" + result);
            } else {
                System.out.println("Cannot extract the item fields.");
            }
        }
    }

    private String getItemFields(String item) {

        StringBuffer pubXmlText = new StringBuffer("\n<" + itemName + ">\n");
        String value = null;

        for (Ruas ruas : ruasList) {

            if (ruas instanceof RuasData) {

                RuasData ruasData = (RuasData) ruas;

                //-- extract the description component
                int startOfRuasPos = item.indexOf(ruasData.getStartMark());
                int endOfRuasPos = item.indexOf(ruasData.getEndMark(), startOfRuasPos);

                if (startOfRuasPos == -1 || endOfRuasPos == -1) {
                    return "failed";
                }

                value = removeTags(item.substring(startOfRuasPos, endOfRuasPos));
            } else {
                RuasInfo ruasInfo = (RuasInfo) ruas;
                value = ruasInfo.getValue();
            }

            String ruasElement = "<" + ruas.getName() + "><![CDATA[" + value + "]]>"+"</"+ruas.getName()+">";
            pubXmlText.append("  " + ruasElement + "\n");

        }

        pubXmlText.append("</" + itemName + ">");

        return pubXmlText.toString();
    }

    /**
     * Return text without HTML tags
     * @param htmlText HTML text whose tags will be removed
     * @return Text without HTML tags
     */
    private String removeTags(String htmlText) {
        htmlText = htmlText.replaceAll("\\<.*?>", " ");
        htmlText = cleanText(htmlText);
        return htmlText;
    }

    private String cleanText(String text) {
        text = text.replaceAll("\\s+", " ");
        text = text.trim();
        return text;
    }

    private void saveToFile() {
        try {
            FileWriter file = new FileWriter(xmlFileName);
            BufferedWriter out = new BufferedWriter(file);
            out.write(xmlText.toString());
            out.close();
        } catch (IOException e) {
        }
    }

    public void start() {
        retrievePages();
        saveToFile();
    }
}
